package cn.com.tarotframework.config;

import cn.com.tarotframework.server.workflow.eu.FlowEvents;
import cn.com.tarotframework.server.workflow.eu.FlowStatus;
import cn.com.tarotframework.server.workflow.po.FlowNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachineContext;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;

import java.util.EnumSet;

/**
 * 流程状态机配置
 */
@Slf4j
@Configuration
@EnableStateMachine
public class FlowStateMachineConfig extends StateMachineConfigurerAdapter<FlowStatus, FlowEvents> {

    /**
     * 配置初始状态
     *
     * @param states 状态
     */
    public void configure(StateMachineStateConfigurer<FlowStatus, FlowEvents> states) throws Exception {
        states.withStates().initial(FlowStatus.EXECUTE_WAIT).states(EnumSet.allOf(FlowStatus.class));
    }

    /**
     * 配置状态转换事件关系
     *
     * @param transitions 事务
     */
    public void configure(StateMachineTransitionConfigurer<FlowStatus, FlowEvents> transitions) throws Exception {
        transitions
                .withExternal().source(FlowStatus.EXECUTE_WAIT).target(FlowStatus.EXECUTE_SUCCESS).event(FlowEvents.EXECUTE_COMPLETE)
                .and()
                .withExternal().source(FlowStatus.EXECUTE_WAIT).target(FlowStatus.EXECUTE_ERROR).event(FlowEvents.EXECUTE_FAIL)
                .and()
                .withExternal().source(FlowStatus.EXECUTE_WAIT).target(FlowStatus.EXECUTE_NOT).event(FlowEvents.EXECUTE_STOP);
    }


    /**
     * 持久化配置
     * 实际使用中，可以配合redis等，进行持久化操作
     *
     */
    @Bean
    public DefaultStateMachinePersister<FlowStatus, FlowEvents, FlowNode> persister() {
        return new DefaultStateMachinePersister<>(new StateMachinePersist<FlowStatus, FlowEvents, FlowNode>() {
            @Override
            public void write(StateMachineContext<FlowStatus, FlowEvents> stateMachineContext, FlowNode flowNode) throws Exception {
                //此处并没有进行持久化操作
//                log.info("根据需求是否选择持久化，此处并没有进行持久化操作");
            }

            @Override
            public StateMachineContext<FlowStatus, FlowEvents> read(FlowNode flowNode) throws Exception {
                //此处直接获取order中的状态，其实并没有进行持久化读取操作
                return new DefaultStateMachineContext(flowNode.getStatus(), null, null, null);
            }
        });
    }
}
